package com.zy.stock.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.zy.stock.domain.Pager;
import com.zy.stock.domain.Stock;
import com.zy.stock.domain.StockTranscation;
import com.zy.stock.domain.UserStockRl;
import com.zy.stock.dto.StockDto;
import com.zy.stock.dto.StockTranscationDto;
import com.zy.stock.dto.UserStockRlDto;
import com.zy.stock.dto.UserStockRlProfitDto;
import com.zy.stock.mapper.StockTranscationMapper;
import com.zy.stock.mapper.UserStockRlMapper;
import com.zy.stock.service.StockTranscationService;
import com.zy.stock.util.CommonUtils;

@Component
@Transactional
public class StockTranscationServiceImp implements StockTranscationService{
	
	private Logger logger = LoggerFactory.getLogger(StockTranscationServiceImp.class);
	
	@Autowired
	private StockTranscationMapper stockTranscationMapper;
	
	@Autowired
	private UserStockRlMapper userStockRlMapper;
	
	@Override
	public Integer save(StockTranscation obj) throws Exception {
		// TODO Auto-generated method stub
		if(obj.getStatus().equalsIgnoreCase("已完成")){
			//更新股票持有状态	
			if(obj.getOperation().equalsIgnoreCase("卖出")){//卖出情况
				BigDecimal cost = calculateSellCost(obj);//获取最新成本
				//处理股票持有关系
				updateUserStockRlOnSell(obj, cost);
			}else{//买入情况
			  if(obj.getOperation().equalsIgnoreCase("建仓")||obj.getOperation().equalsIgnoreCase("首补")||obj.getOperation().equalsIgnoreCase("二次补仓")){
				  BigDecimal cost = calculateBuyCost(obj);//获取最新成本
	                //处理股票持有关系
	                updateUserStockRlOnBuy(obj, cost);
              }else{
                if(obj.getOperation().equalsIgnoreCase("现金分红")){
//                  calculateCost(baseCashNum, shareCash, rl);
                }else{
                  if(obj.getOperation().equalsIgnoreCase("股票分红")){
//                    dealStockShare(baseStockNum, shareStockNum, rl);
                  }
                }
              }
			}
		}else{
			//首次创建交易记录 通常状态为未完成 这时候初始化交易前仓的状态
			//保留操作之前的仓的状态json
			UserStockRl originRl = userStockRlMapper.findById(obj.getUserStockRlId());//卖出的股票所属的关系
			//根据之前的状态判断 是否要根据之前状态计算
			if(originRl!=null){
				obj.setUserStockRlJsonStr(JSONObject.toJSONString(originRl));
			}			
		}
		if(obj.getCreateTime()==null){
			obj.setCreateTime(new Date());
		}
		logger.info("保存交易记录.."+JSONObject.toJSONString(obj));
		return stockTranscationMapper.save(obj);
	}
	
	/**
	 * 卖出股票以后 完成计算新成本 然后更新保存 
	 * 股票持有关系 并且需要转移剩余股票到其他栏里面
	 * 需要根据卖出的不同情况 处理变更成本和转移到当年其他里面去
	 * @param obj
	 * @param cost
	 */
	private void updateUserStockRlOnSell(StockTranscation obj, BigDecimal cost) {
		// TODO Auto-generated method stub
		UserStockRl rl = null;
		if(StringUtils.isNotEmpty(obj.getUserStockRlJsonStr())){
			rl = JSONObject.parseObject(obj.getUserStockRlJsonStr(), UserStockRl.class);
			obj.setCost(rl.getCost());//记录一下交易时候股票的成本
			Double totalCost = rl.getCost()*rl.getNum();//之前总花费
			Integer sellNum = obj.getOperateNum();//卖出数
			Integer currentNum = rl.getNum();//当前持有数
			Integer restNum = currentNum-sellNum;//卖出后剩余数
			Double stockCost = obj.getValue()*obj.getOperateNum();//成交金额
			
			if(restNum==0){//全卖了 那成本就还是以前的成本 不要再计算摊薄的成本了 rl关系存量改为0
				rl.setStatus("已卖出");
				rl.setNum(restNum);
				logger.info("修改股票持有关系..."+JSONObject.toJSONString(rl));
				userStockRlMapper.update(rl);
			}else{
				//在没有其他的情况下 最简单 直接把剩下的股票关系变更为其他 然后 修改一下成本价和数量
				rl.setNum(restNum);
				rl.setCost(cost.doubleValue());
				rl.setStatus("其他");
				logger.info("修改股票持有关系..."+JSONObject.toJSONString(rl));
				userStockRlMapper.update(rl);
			}
		}else{
			rl = userStockRlMapper.findById(obj.getUserStockRlId());//卖出的股票所属的关系
			obj.setCost(rl.getCost());//记录一下交易时候股票的成本
			Double totalCost = rl.getCost()*rl.getNum();//之前总花费
			Integer sellNum = obj.getOperateNum();//卖出数
			Integer currentNum = rl.getNum();//当前持有数
			Integer restNum = currentNum-sellNum;//卖出后剩余数
			Double stockCost = obj.getValue()*obj.getOperateNum();//成交金额
		
			if(restNum==0){//全卖了 那成本就还是以前的成本 不要再计算摊薄的成本了 rl关系存量改为0
				rl.setStatus("已卖出");
				rl.setNum(restNum);
				logger.info("修改股票持有关系..."+JSONObject.toJSONString(rl));
				userStockRlMapper.update(rl);
			}else{
				//在没有其他的情况下 最简单 直接把剩下的股票关系变更为其他 然后 修改一下成本价和数量
				rl.setNum(restNum);
				rl.setCost(cost.doubleValue());
				rl.setStatus("其他");
				logger.info("修改股票持有关系..."+JSONObject.toJSONString(rl));
				userStockRlMapper.update(rl);
			}
		}	
	}

	/**
	 * 在卖出的时候 计算一下新的股票成本 
	 * @param obj
	 * @return
	 * @throws Exception 
	 */
	private BigDecimal calculateSellCost(StockTranscation obj) throws Exception{
		BigDecimal cost = new BigDecimal(0);
		Integer companyCost = 0;//券商佣金
		Integer guoHuCost = 0;//过户费
		Integer yinHuaCost = 0;//印花税
		Double stockCost = obj.getValue()*obj.getOperateNum();//成交金额
		Double totalCost = new Double(0);//之前总花费
		Integer sellNum = obj.getOperateNum();//卖出数
		Integer currentNum = 0;//当前持有数
		Integer restNum = 0;//剩余数
		
		companyCost = (int) (obj.getOperateNum()*obj.getValue()*0.00025);
		
		if(companyCost<=5){
			companyCost = 5;
		}
		logger.info("得到券商佣金 is..."+companyCost);//得到券商佣金
		
		if(obj.getStockCode().indexOf("6")==0){
			guoHuCost = obj.getOperateNum()/1000;
			if(guoHuCost<=1){
				guoHuCost = 1;
			}
		}
		
		
		logger.info("得到过户费 is..."+guoHuCost);//得到过户费
		
		yinHuaCost = (int) (stockCost*0.001);//得到印花税
		logger.info("得到印花税 is..."+yinHuaCost);
		
		//计算新成本
		UserStockRl rl = null;
		if(StringUtils.isNotEmpty(obj.getUserStockRlJsonStr())){
			//有交易之前的仓的json串 则用这个计算
			rl = JSONObject.parseObject(obj.getUserStockRlJsonStr(), UserStockRl.class);
		}else{
			//没有json串 说明是直接添加已完成状态的交易记录
			rl= userStockRlMapper.findById(obj.getUserStockRlId());
			//保存一下 交易前的状态
			obj.setUserStockRlJsonStr(JSONObject.toJSONString(rl));
		}
		currentNum+=rl.getNum();//当前股票数量累加
		totalCost+=rl.getCost()*rl.getNum();//当前总成本累加
	
		restNum = currentNum-sellNum;//剩余股票数
		
		if(restNum==0){//全卖了 那成本就还是以前的成本
			
		}else{
			//新的成本 是之前的总投入-这次卖出的净收入/剩余股票数
			cost = new BigDecimal((totalCost-stockCost+companyCost+guoHuCost+yinHuaCost)/restNum);
			cost = cost.setScale(2, BigDecimal.ROUND_HALF_UP);
		}
		//保存最终交易金额 用于计算盈亏
		BigDecimal incomeCash = new BigDecimal(stockCost-(companyCost+guoHuCost+yinHuaCost));
		incomeCash = incomeCash.setScale(2, BigDecimal.ROUND_HALF_UP);
		obj.setIncomeCash(incomeCash);
		logger.info("卖出后实际收入金额..."+incomeCash.toString());
		if(obj.getId()!=null){
			stockTranscationMapper.update(obj);
		}else{
//			stockTranscationMapper.save(obj);
		}
		logger.info("新的成本 is..."+cost);
		return cost;
	}
	
	
	
	
	/**
	 * 买入价 
	 * 买入金额=买入价*买入金额
	 *  1. 券商佣金:按每次下单买入股票金额的0.025%收取，但最低为5元；
	 *	2. 过户费：仅针对沪市的股票（就是代码6打头的）收取，按每次下单成交的1元/千股计费，但最低为1元，深市不收取过户费
	 * 计算成本
	 * @param obj
	 */
	private BigDecimal calculateBuyCost(StockTranscation obj){
		Integer companyCost = 0;//券商佣金
		Integer guoHuCost = 0;//过户费
		Double stockCost = new Double(0);//成交金额
		Double totalCost = new Double(0);//总花费
		Integer totalNum = obj.getOperateNum();//总股票数
		companyCost = (int) (obj.getOperateNum()*obj.getValue()*0.00025);
		
		if(companyCost<=5){
			companyCost = 5;
		}
		logger.info("券商佣金 is..."+companyCost);
		
		if(obj.getStockCode().indexOf("6")==0){
			guoHuCost = obj.getOperateNum()/1000;
			if(guoHuCost<=1){
				guoHuCost = 1;
			}
		}
		logger.info("过户费 is..."+guoHuCost);
		
		//结合买入股票的费用一起计算总成本
		stockCost = obj.getValue()*obj.getOperateNum();
		//如果是之前有持有情况需要加在一起计算成本
		if(obj.getOperation().equalsIgnoreCase("首补")||obj.getOperation().equalsIgnoreCase("二次补仓")){
			UserStockRlDto dto = new UserStockRlDto();
			dto.setUserName(obj.getUserName());
			dto.setStockCode(obj.getStockCode());
			dto.setYears(obj.getYears());
			//计算新成本
			UserStockRl rl = null;
			if(StringUtils.isNotEmpty(obj.getUserStockRlJsonStr())){
				//有交易之前的仓的json串 则用这个计算
				rl = JSONObject.parseObject(obj.getUserStockRlJsonStr(), UserStockRl.class);
				obj.setUserStockRlJsonStr(JSONObject.toJSONString(rl));
			}else{
				//没有json串 说明是直接添加已完成状态的交易记录
				rl= userStockRlMapper.findById(obj.getUserStockRlId());
				//保存一下 交易前的状态
				obj.setUserStockRlJsonStr(JSONObject.toJSONString(rl));
			}
			stockCost+=rl.getCost()*rl.getNum();
			totalNum+=rl.getNum();
		}
		totalCost = stockCost+companyCost+guoHuCost;
		logger.info("总花费 is..."+totalCost);
		BigDecimal cost = new BigDecimal(totalCost/totalNum);
		cost = cost.setScale(2, BigDecimal.ROUND_HALF_UP);
		logger.info("计算后成本 is..."+cost);
		//保存最终交易金额 用于计算盈亏
		BigDecimal payCash = new BigDecimal(obj.getValue()*obj.getOperateNum()+companyCost+guoHuCost);
		payCash = payCash.setScale(2, BigDecimal.ROUND_HALF_UP);
		obj.setPayCash(payCash);
		logger.info("买入实际花费..."+payCash.toString());
		stockTranscationMapper.update(obj);
		return cost;
	}
		
	@Override
	public Pager<List<StockTranscation>> findByCase(
			Pager<StockTranscationDto> pager) throws Exception {
		// TODO Auto-generated method stub
		Pager<List<StockTranscation>> result = new Pager<List<StockTranscation>>();
		try{
			StockTranscationDto obj = pager.getT();
			Integer total = stockTranscationMapper.getCount(obj);
			Integer totalpage = CommonUtils.getTotalPage(pager, total);
			Integer begin = (pager.getPagenow() - 1) * pager.getSize();
			obj.setStart(begin);
			obj.setSize(pager.getSize());
			obj.setOrder(pager.getOrder());
			obj.setOrderCol(pager.getOrderCol());
			List<StockTranscation> list = stockTranscationMapper.findByCase(obj);
			result.setTotal(total);
			result.setT(list);
			result.setTotalpage(totalpage);
		}catch(Exception e){
			e.printStackTrace();
			throw new Exception("BillServiceImp.class findByCase function error : " + e.toString());
		}
		return result;
	}
	
	/**
	 * 买入股票以后 完成计算新成本 然后更新保存 股票持有关系
	 * @param obj
	 * @param cost
	 */
	private void updateUserStockRlOnBuy(StockTranscation obj,BigDecimal cost){
		UserStockRl rl = null;
		if(StringUtils.isNotEmpty(obj.getUserStockRlJsonStr())){
			//有交易之前的仓的json串 则用这个计算
			rl = JSONObject.parseObject(obj.getUserStockRlJsonStr(), UserStockRl.class);
			rl.setNum(rl.getNum()+obj.getOperateNum());//增加持有数字
			rl.setUpdateTime(new Date());
			rl.setCost(cost.doubleValue());
			rl.setStatus(obj.getOperation());
			rl.setUpdateTime(new Date());
			logger.info("修改股票持有关系..."+JSONObject.toJSONString(rl));
			userStockRlMapper.update(rl);
		}else{
			//没有json串 说明是直接添加已完成状态的交易记录
			//之前没有创建关联关系 则需要创建新的关联关系
			if(obj.getUserStockRlId()!=null){
				rl = userStockRlMapper.findById(obj.getUserStockRlId());
				rl.setCost(cost.doubleValue());
				rl.setCreateTime(new Date());
				rl.setNum(obj.getOperateNum());
				rl.setStatus(obj.getOperation());
				rl.setStockCode(obj.getStockCode());
				rl.setStockId(obj.getStockId());
				rl.setStockName(obj.getStockName());
				rl.setStoreNum(obj.getUserName()+"_"+obj.getStockName()+"_"+obj.getYears()+"_1");
				rl.setUserId(obj.getUserId());
				rl.setUserName(obj.getUserName());
				rl.setYears(obj.getYears());
				logger.info("修改股票持有关系..."+JSONObject.toJSONString(rl));
				userStockRlMapper.update(rl);
			}else{
				UserStockRlDto dto = new UserStockRlDto();
				dto.setUserId(obj.getUserId());
				dto.setStockCode(obj.getStockCode());
				List<UserStockRl> rls = userStockRlMapper.findByCase(dto);
				rl = new UserStockRl();
				rl.setCost(cost.doubleValue());
				rl.setCreateTime(new Date());
				rl.setNum(obj.getOperateNum());
				rl.setStatus(obj.getOperation());
				rl.setStockCode(obj.getStockCode());
				rl.setStockId(obj.getStockId());
				rl.setStockName(obj.getStockName());
				if(rls!=null&&rls.size()>0){
					int num = rls.size()+1;
					rl.setStoreNum(obj.getUserName()+"_"+obj.getStockName()+"_"+obj.getYears()+"_"+String.valueOf(num));
				}else{
					rl.setStoreNum(obj.getUserName()+"_"+obj.getStockName()+"_"+obj.getYears()+"_1");
				}
				rl.setUserId(obj.getUserId());
				rl.setUserName(obj.getUserName());
				rl.setYears(obj.getYears());
				Integer rlId = userStockRlMapper.save(rl);
				obj.setUserStockRlId(rl.getId());			
			}
		}
	}
	
	@Override
	public void deleteById(Integer id) {
		// TODO Auto-generated method stub
		//如果删除的是一个已完成的交易 则删除的时候要把仓的状态 还原成未交易的时候 
		StockTranscation obj = stockTranscationMapper.findById(id);
		if("已完成".equals(obj.getStatus())){
			UserStockRl rl = null;
			if(StringUtils.isNotEmpty(obj.getUserStockRlJsonStr())){
				//有交易之前的仓的json串 则用这个计算
				rl = JSONObject.parseObject(obj.getUserStockRlJsonStr(), UserStockRl.class);
				userStockRlMapper.update(rl);
			}else{
				userStockRlMapper.deleteById(obj.getUserStockRlId());
			}
		}
		stockTranscationMapper.deleteById(id);
	}

	@Override
	public void update(StockTranscation obj) throws Exception {
		// TODO Auto-generated method stub
		StockTranscation original = stockTranscationMapper.findById(obj.getId());
		obj.setUserStockRlJsonStr(original.getUserStockRlJsonStr());
		if(obj.getStatus().equalsIgnoreCase("已完成")){
			//更新股票持有状态	
			if(obj.getOperation().equalsIgnoreCase("卖出")){//卖出情况
				BigDecimal cost = calculateSellCost(obj);//获取最新成本
				//处理股票持有关系
				updateUserStockRlOnSell(obj, cost);
			}else{//买入情况
			  if(obj.getOperation().equalsIgnoreCase("建仓")||obj.getOperation().equalsIgnoreCase("首补")||obj.getOperation().equalsIgnoreCase("二次补仓")){
	              BigDecimal cost = calculateBuyCost(obj);//获取最新成本
	                //处理股票持有关系
	                updateUserStockRlOnBuy(obj, cost);
			  }else{
			    if(obj.getOperation().equalsIgnoreCase("现金分红")){
			      
			    }else{
			      if(obj.getOperation().equalsIgnoreCase("股票分红")){
			        
			      }
			    }
			  }
			}
		}
		obj.setUpdateTime(new Date());
		logger.info("更新交易记录.."+JSONObject.toJSONString(obj));
		stockTranscationMapper.update(obj);
	}
	
	/**
     * 计算现金分红
     * @param baseCashNum
     * @param shareCash
     * @param stockId
     * @param rl
     * @throws Exception 
     */
    @Transactional(propagation=Propagation.REQUIRES_NEW) 
    private void calculateCost(Integer baseCashNum, Double shareCash,UserStockRl rl) throws Exception{
        //计算实际送了多少钱
        Double realShare = (rl.getNum()/baseCashNum)*shareCash; 
        //计算实际收入多少钱 交10%税
        BigDecimal incomeCash = new BigDecimal(realShare*0.9);
        //计算新的摊薄成本
        Double totalCost = rl.getNum()*rl.getCost();
        BigDecimal newCost = new BigDecimal((totalCost-incomeCash.doubleValue())/rl.getNum());
        newCost = newCost.setScale(2, BigDecimal.ROUND_HALF_UP);;
        rl.setCost(newCost.doubleValue());
            
        //保存现金分红记录
        StockTranscation st = new StockTranscation();
        st.setUserId(rl.getUserId());
        st.setUserName(rl.getUserName());
        st.setStockId(rl.getStockId());
        st.setStockCode(rl.getStockCode());
        st.setStockName(rl.getStockName());
        st.setUserStockRlId(rl.getId());
        st.setOperateNum(rl.getNum());
        st.setYears(rl.getYears());
        st.setOperation("现金分红");
        st.setStatus("已完成");
        st.setIncomeCash(incomeCash);
        st.setCreateTime(new Date());
        
        //保留操作之前的仓的状态json
        UserStockRl originRl = userStockRlMapper.findById(st.getUserStockRlId());//卖出的股票所属的关系
        //根据之前的状态判断 是否要根据之前状态计算
        if(originRl!=null){
            st.setUserStockRlJsonStr(JSONObject.toJSONString(originRl));
        }
        
        stockTranscationMapper.save(st);
    }
    	
	@Override
	public StockTranscation findById(Integer id) {
		// TODO Auto-generated method stub
		return stockTranscationMapper.findById(id);
	}

	@Override
	public void ignoreById(Integer id) {
		// TODO Auto-generated method stub
		StockTranscation obj = stockTranscationMapper.findById(id);
		obj.setStatus("已忽略");
		stockTranscationMapper.update(obj);
	}

	@Override
	public void ignoreYesterday() {
		// TODO Auto-generated method stub
		stockTranscationMapper.ignoreYesterday("未完成");
	}

	@Override
	public double getTotalIncome(Integer userStockRlId) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public double getTotalPayCash(Integer userStockRlId) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public double getProfit(Integer userStockRlId) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public List<UserStockRlProfitDto> findProfit(Integer userId,String year) {
		// TODO Auto-generated method stub
		return stockTranscationMapper.findProfit(userId,year);
	}
	
}	
